package org.gdstash.ui.stash;

import org.gdstash.character.GDChar;
import org.gdstash.file.DDSLoader;
import org.gdstash.item.GDItem;
import org.gdstash.ui.GDStashFrame;
import org.gdstash.ui.GDUITransfer;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.util.GDImagePool;

import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.List;

public class GDContainerMapPane extends AdjustablePanel implements GDUIMultiContainer {
    private static final Color COLOR_RED;
    private static final Color COLOR_DARK_RED;
    private static final Color COLOR_WHITE;
    private static final Color COLOR_GREEN;
    private BufferedImage bgImage;
    private GDUIInventory uiInventory;
    private GDUITransfer uiTransfer;
    private List<GDUIContainer> containers;
    private GDUIContainer selContainer;

    public GDContainerMapPane() {
        this(null, null, GDImagePool.getCharStashBG());
    }

    public GDContainerMapPane(final GDUIInventory uiInventory, final GDUITransfer uiTransfer, final BufferedImage bgImage) {
        this.uiInventory = uiInventory;
        this.uiTransfer = uiTransfer;
        this.bgImage = bgImage;
        this.containers = new LinkedList<GDUIContainer>();
        this.addMouseListener(new GDMouseListener());
        this.addMouseMotionListener(new GDMouseListener());
    }

    @Override
    public void adjustUI() {
    }

    static {
        COLOR_RED = Color.RED;
        COLOR_DARK_RED = new Color(127, 0, 0);
        COLOR_WHITE = Color.WHITE;
        COLOR_GREEN = new Color(83, 255, 40);
    }

    public void setBGImage(final BufferedImage bgImage) {
        this.bgImage = bgImage;
    }

    private GDUIContainer findSelectedContainer(final MouseEvent e) {
        return this.findSelectedContainer(e.getX(), e.getY());
    }

    private GDUIContainer findSelectedContainer(final int xCoord, final int yCoord) {
        if (this.containers == null) {
            return null;
        }
        final int x = xCoord;
        final int y = yCoord;
        GDUIContainer container = null;
        for (final GDUIContainer uic : this.containers) {
            int xp = uic.getXOffset();
            int yp = uic.getYOffset();
            final int w = uic.getWidth();
            final int h = uic.getHeight();
            if (GDStashFrame.iniConfig.sectUI.graphicScale != 100) {
                xp = xp * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
                yp = yp * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            }
            if (xp <= x && xp + w >= x && yp <= y && yp + h >= y) {
                container = uic;
                break;
            }
        }
        return container;
    }

    private void notifyPages(final MouseEvent e) {
        if (this.containers != null) {
            for (final GDUIContainer container : this.containers) {
                container.dispatchEvent(e);
            }
        }
    }

    public void updateConfig() {
        if (this.containers != null) {
            for (final GDUIContainer container : this.containers) {
                if (container != null) {
                    container.updateConfig();
                }
            }
        }
    }

    @Override
    public void clearContainers() {
        this.containers.clear();
    }

    @Override
    public void addContainer(final GDUIContainer container) {
        if (container == null) {
            return;
        }
        this.containers.add(container);
        this.layoutContainers();
    }

    @Override
    public void layoutContainers() {
        this.repaint();
    }

    @Override
    public boolean addItem(final GDItem item, final int action, final int xCoord, final int yCoord) {
        boolean added = false;
        final GDUIContainer container = this.findSelectedContainer(xCoord, yCoord);
        if (container != null) {
            added = container.addItem(item, action, xCoord, yCoord);
            this.layoutContainers();
        }
        return added;
    }

    @Override
    public boolean deleteItem(final GDItem item, final int action, final boolean update) {
        if (item == null) {
            return true;
        }
        if (this.containers == null) {
            return false;
        }
        boolean deleted = false;
        for (final GDUIContainer container : this.containers) {
            if (container.deleteItem(item, action, update)) {
                deleted = true;
                break;
            }
        }
        if (update) {
            this.layoutContainers();
        }
        return deleted;
    }

    @Override
    public boolean hasChanged() {
        if (this.containers == null) {
            return false;
        }
        boolean hasChanged = false;
        for (final GDUIContainer container : this.containers) {
            if (container.hasChanged()) {
                hasChanged = true;
                break;
            }
        }
        return hasChanged;
    }

    @Override
    public List<GDItem> getItemList(final int action) {
        final List<GDItem> listAll = new LinkedList<GDItem>();
        if (this.containers == null) {
            return listAll;
        }
        for (final GDUIContainer container : this.containers) {
            final List<GDItem> list = container.getItemList(action);
            if (list != null) {
                listAll.addAll(list);
            }
        }
        return listAll;
    }

    @Override
    public void refresh() {
        if (this.containers != null) {
            for (final GDUIContainer container : this.containers) {
                container.refresh();
            }
            this.layoutContainers();
        }
    }

    public void paintComponent(final Graphics g) {
        super.paintComponent(g);
        if (this.bgImage == null) {
            return;
        }
        g.drawImage(this.drawGraphics(), 0, 0, null);
    }

    @Override
    public Dimension getPreferredSize() {
        if (this.bgImage == null) {
            return super.getPreferredSize();
        }
        final int w = this.bgImage.getWidth() * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
        final int h = this.bgImage.getHeight() * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
        return new Dimension(w, h);
    }

    @Override
    public Dimension getMaximumSize() {
        return this.getPreferredSize();
    }

    @Override
    public Dimension getMinimumSize() {
        return this.getPreferredSize();
    }

    public int getPreferredWidth() {
        return (int) this.getPreferredSize().getWidth();
    }

    public int getPreferredHeight() {
        return (int) this.getPreferredSize().getHeight();
    }

    private BufferedImage drawGraphics() {
        if (this.bgImage == null) {
            return null;
        }
        Graphics g = null;
        BufferedImage image = null;
        image = new BufferedImage(this.bgImage.getWidth(), this.bgImage.getHeight(), this.bgImage.getType());
        g = image.createGraphics();
        g.drawImage(this.bgImage, 0, 0, null);
        if (this.containers != null) {
            for (final GDUIContainer container : this.containers) {
                final BufferedImage img = container.drawGraphics();
                g.drawImage(img, container.getXOffset(), container.getYOffset(), null);
            }
        }
        if (GDStashFrame.iniConfig.sectUI.graphicScale != 100) {
            final int w = image.getWidth() * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            final int h = image.getHeight() * GDStashFrame.iniConfig.sectUI.graphicScale / 100;
            image = DDSLoader.getScaledImage(image, w, h);
        }
        return image;
    }

    @Override
    public void setChar(final GDChar gdc) {
    }

    private class GDMouseListener extends MouseInputAdapter {
        @Override
        public void mousePressed(final MouseEvent e) {
            if (GDContainerMapPane.this.containers == null) {
                return;
            }
            GDContainerMapPane.this.selContainer = GDContainerMapPane.this.findSelectedContainer(e);
            GDContainerMapPane.this.notifyPages(e);
            GDContainerMapPane.this.layoutContainers();
        }

        @Override
        public void mouseMoved(final MouseEvent e) {
            if (GDContainerMapPane.this.containers == null) {
                return;
            }
            GDContainerMapPane.this.selContainer = GDContainerMapPane.this.findSelectedContainer(e);
            GDContainerMapPane.this.notifyPages(e);
            GDContainerMapPane.this.layoutContainers();
        }
    }
}
